#include <config.h>
#include <board.h>
#include <init.h>
#include <os.h>
#include <bitmap.h>
#include <bitops.h>
#include <settings.h>
#include <stm32f0xx.h>
#include "device.h"
#include "stm32_io.h"
#include "printk.h"

#define PORT_LED_RED                 GPIOA                  //LED
#define PIN_LED_RED                  GPIO_Pin_3

#define LED_RED_ON                   (PORT_LED_RED->BRR = PIN_LED_RED)
#define LED_RED_OFF                  (PORT_LED_RED->BSRR  = PIN_LED_RED)
#define LED_RED_TOGGLE               (PORT_LED_RED->ODR ^= PIN_LED_RED)

#define LED_EXPIRES	10 /*(*10ms)*/

static struct device led_dev;
static int led_flash_cnt = 0;
static enum LED_state led_s = STATE_LED_OFF;

static void led_blink_500ms(void)
{
    static uint32_t led_count = 0 ;
    if(++led_count >5 )
    {
        led_count = 0;
        LED_RED_TOGGLE;
    }

}
static void led_tmr_cb(struct soft_timer *st)
{
    uint8_t cmd = (uint8_t)led_s;
    st->expires = jiffies +  LED_EXPIRES;
    soft_timer_add(st);
	
	if(led_flash_cnt > 0)
	{
		led_flash_cnt --;
		LED_RED_TOGGLE;
		return ;
	}
    switch (cmd)
    {
    case STATE_LED_BLINK:
        LED_RED_TOGGLE;
        break;
    case STATE_LED_ON:
        LED_RED_ON;
        break;
    case STATE_LED_OFF:
        LED_RED_OFF;
        break;
    case STATE_LED_BLINK_500:
        led_blink_500ms();
        break;
    default:
        LED_RED_OFF;
        break;
    }
}

static err_t led_ctrl(device_t *dev, uint8_t cmd, void *args)
{
    if((enum LED_state)cmd == STATE_LED_FLASH_3)
	{
		led_flash_cnt = 6;
	}
	else
	{
		led_s = (enum LED_state)cmd;
	}
    return 0;
}

static struct device_ops led_ops =
{
    .ctrl = led_ctrl,
};

static void led_gpio_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin =PIN_LED_RED;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(PORT_LED_RED, &GPIO_InitStructure);
	LED_RED_OFF;
}

static struct soft_timer led_tmr =
{
    .expires = INITIAL_JIFFIES + configHZ / 100,
    .cb      = led_tmr_cb,
};

int board_setup_led(void)
{
	led_gpio_init();
	led_dev.ops = &led_ops;
	device_register(&led_dev, "led", 0);
	soft_timer_add(&led_tmr);
  return 0;
}
device_initcall(board_setup_led);

/*
 *PIR GPIO setup
*/
#ifdef configUSING_INPUT
#define PIR_PORT            GPIOA
#define PIR_PIN             GPIO_Pin_6
#define PIR_PORT_SOURCE     EXTI_PortSourceGPIOA
#define PIR_PIN_SOURCE      EXTI_PinSource6
#define PIR_EXTI_LINE       EXTI_Line6
static void pir_gpio_init(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    
	GPIO_InitStructure.GPIO_Pin = PIR_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(PIR_PORT, &GPIO_InitStructure);
    
    EXTI_ClearITPendingBit(PIR_EXTI_LINE);	
   	EXTI_InitStructure.EXTI_Line = PIR_EXTI_LINE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling ;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);    	
    SYSCFG_EXTILineConfig(PIR_PORT_SOURCE, PIR_PIN_SOURCE);
    
    NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void EXTI4_15_IRQHandler()
{
     if(EXTI_GetITStatus(PIR_EXTI_LINE) != RESET)
    {                     
        EXTI_ClearITPendingBit(PIR_EXTI_LINE);// Clear the EXTI line pending bit
        //
    }
}

static int pir_gpio_setup(void)
{
    pir_gpio_init();
    return 0;
}
device_initcall(pir_gpio_setup);
#endif